﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Xml;

namespace ParameterManagementSystem
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            xmlFilesList = new Dictionary<string, XmlFile>();
            autoTestCtrl = new AutomaticTestsUserControl(ref xmlFilesList, ref listBoxXmlFiles);
            tabPage2.Controls.Add(autoTestCtrl);
            fileGeneratorControl = new FileGeneratorUserControl(ref xmlFilesList, ref listBoxXmlFiles);
            tabPage3.Controls.Add(fileGeneratorControl);
            searchingParameters = new SearchingParameters();
            compareUserControl = new CompareUserControl(ref xmlFilesList, ref listBoxXmlFiles);
            tabPage5.Controls.Add(compareUserControl);
        }

        public void UpdateComboBoxTags()
        {
            comboBoxSearchingTags.Items.Clear();
            foreach (Tag item in tagPanel1.tagList.Values)
            {
                comboBoxSearchingTags.Items.Add(item.name);
            }
        }

        private void newDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteDatabase();
            ClearXmlFilesList();
        }

        private void ClearXmlFilesList()
        {
            xmlFilesList.Clear();
            listBoxXmlFiles.Items.Clear();
            fileGeneratorControl.clearFileTree();
        }

        private void DeleteDatabase()
        {
            this.Text = "Parameter Manager";
            dataBase = null;
        }

        private void SetNewDatabase(string name)
        {
            dataBase = new DataBase(name);
            this.Text = "Parameter Manager: " + Path.GetFileName(name);
            autoTestCtrl.Database = dataBase;
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;
            dialog.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                foreach( string fileName in dialog.FileNames ){
                    if (!File.Exists(fileName))
                    {
                        continue;
                    }
                    XmlFile item = new XmlFile();

                    XmlFile[] filesArray = new XmlFile[xmlFilesList.Values.Count];
                    xmlFilesList.Values.CopyTo(filesArray, 0);
                    item.GenerateID(filesArray);
                    item.name = Path.GetFileName(fileName);
                    item.content = File.ReadAllText(fileName);
                    item.timeStamp = File.GetLastWriteTime(fileName);

                    if (xmlFilesList.ContainsKey(item.name))
                    {
                        continue;
                    }
                    XmlFilesList_AddItem(item);
                }
            }
        }

        private void XmlFilesList_AddItem( XmlFile item )
        {
            xmlFilesList.Add(item.name, item);
            listBoxXmlFiles.Items.Add(item.name);
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            Object[] selectedItems = new Object[listBoxXmlFiles.SelectedItems.Count];
            listBoxXmlFiles.SelectedItems.CopyTo(selectedItems, 0);
            foreach (Object item in selectedItems)
            {
                if (item != null && xmlFilesList.ContainsKey((string)item))
                {
                    XmlFile file = xmlFilesList[(string)item];
                    List<XmlTagRelation> relationsToDelete = new List<XmlTagRelation>();
                    foreach (XmlTagRelation relation in tagPanel1.relationsList)
                    {
                        if (relation.xmlFileID == file.id)
                        {
                            relationsToDelete.Add(relation);
                        }
                    }
                    foreach (XmlTagRelation relation in relationsToDelete)
                    {
                        tagPanel1.relationsList.Remove(relation);
                    }
                    xmlFilesList.Remove((string)item);
                    listBoxXmlFiles.Items.Remove((string)item);
                }
            }

            if( (listBoxXmlFiles.Items.Count == 0) || (listBoxXmlFiles.SelectedItems.Count == 0))
            {
                fileGeneratorControl.clearFileTree();
            }
        }

        private void openDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "mdb files (*.mdb)|*.mdb";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                if (!File.Exists(dialog.FileName))
                {
                    return;
                }
                SetNewDatabase(dialog.FileName);

                ClearXmlFilesList();
                XmlFile[] array = dataBase.LoadDataBaseContent();
                listBoxXmlFiles.SuspendLayout();
                foreach (XmlFile item in array)
                {
                    if( ! xmlFilesList.ContainsKey( item.name ) )
                    {
                        XmlFilesList_AddItem(item);
                    }
                }
                listBoxXmlFiles.ResumeLayout();
                listBoxXmlFiles.PerformLayout();

                tagPanel1.LoadTagsFromDatabase(dataBase);
                tagPanel1.LoadRelationsFromDatabase(dataBase);
            }
        }

        private void saveDatabaseAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "mdb files (*.mdb)|*.mdb";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                SaveFileListToDatabase(dialog.FileName);
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dataBase != null)
            {
                SaveFileListToDatabase(dataBase.Name);
            }
            else
            {
                saveDatabaseAsToolStripMenuItem_Click(sender, e);
            }
        }

        private void SaveFileListToDatabase(string name)
        {
            SetNewDatabase(name);

            if (File.Exists(name))
            {
                dataBase.DeleteAllData("XML_TAG_RELATION");
                dataBase.DeleteAllData("XML_TABLE");
                dataBase.DeleteAllData("TAGS");
                dataBase.DeleteAllData("USER");
            }
            else if (!dataBase.CreateNewDatabase())
            {
                MessageBox.Show("Database " + Path.GetFileName(name) + " could not be created",
                        "Error creating new database",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                DeleteDatabase();
                return;
            }

            XmlFile[] filesArray = new XmlFile[xmlFilesList.Values.Count];
            xmlFilesList.Values.CopyTo(filesArray, 0);
            dataBase.SaveFiles(filesArray);

            tagPanel1.SaveTags(dataBase);
            tagPanel1.SaveRelations(dataBase);
        }

        private void listBoxXmlFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxXmlFiles.SelectedItem == null)
            {
                return;
            }
            XmlFile file = xmlFilesList[(string)( listBoxXmlFiles.SelectedItem )];
            labelTimestamp.Text = file.timeStamp.ToString();

            fileGeneratorControl.recreateFileTree();

            ListBox.SelectedIndexCollection indices = listBoxXmlFiles.SelectedIndices;

            List<int> id_list = new List<int>();
            foreach (int i in indices)
            {
                id_list.Add(i);
            }
            tagPanel1.SelectedXmlID = id_list;

        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            textBoxSearchName.Text = "";
            radioButtonSearchNone.Checked = true;
            parameterViewList.ClearParameterList();
            searchingParameters.Parameters.Clear();
            searchingParameters.SearchingTagsIDs.Clear();
            listBoxSearchingTags.Items.Clear();
            ReloadListBox();
            ClearSearchParameterTextBoxes();
        }

        private void buttonSearch_Click(object sender, EventArgs e)
        {
            ReloadListBox();
        }

        private void ReloadListBox()
        {
            listBoxXmlFiles.Items.Clear();
            foreach (XmlFile item in xmlFilesList.Values)
            {
                if (textBoxSearchName.Text != "")
                {
                    if (item.name == null || !item.name.Contains(textBoxSearchName.Text))
                    {
                        continue;
                    }
                }
                if (searchingParameters.SearchingTagsIDs.Count > 0)
                {
                    bool containsAllTags = true;
                    foreach (int tagID in searchingParameters.SearchingTagsIDs)
                    {
                        bool fileContainsTag = false;
                        foreach (XmlTagRelation relation in tagPanel1.relationsList)
                        {
                            if (relation.xmlFileID == item.id && tagID == relation.tagID)
                            {
                                fileContainsTag = true;
                                break;
                            }
                        }

                        if (!fileContainsTag)
                        {
                            containsAllTags = false;
                            break;
                        }
                    }

                    if (!containsAllTags)
                    {
                        continue;
                    }
                }
                if (!radioButtonSearchNone.Checked)
                {
                    if (radioButtonSearchAfter.Checked && item.timeStamp < dateTimePickerSearchFrom.Value)
                    {
                        continue;
                    }
                    if (radioButtonSearchBefore.Checked && item.timeStamp > dateTimePickerSearchFrom.Value)
                    {
                        continue;
                    }
                    if (radioButtonSearchBetween.Checked )
                    {
                        if (item.timeStamp < dateTimePickerSearchFrom.Value || item.timeStamp > dateTimePickerSearchTo.Value)
                        {
                            continue;
                        }
                    }
                }
                bool fullfillAllParameters = true;
                foreach( ParameterSearchValue param in searchingParameters.Parameters)
                {
                    if (!item.CompareToParameterSearchValue(param))
                    {
                        fullfillAllParameters = false;
                        continue;
                    }
                }
                if (!fullfillAllParameters)
                {
                    continue;
                }
                listBoxXmlFiles.Items.Add(item.name);
            }
            
        }

        private void radioButtonSearchAfter_CheckedChanged(object sender, EventArgs e)
        {
            dateTimePickerSearchFrom.Visible = true;
            dateTimePickerSearchTo.Visible = false;
            dateTimePickerSearchFrom.Location = new System.Drawing.Point(184, 43);
        }

        private void radioButtonSearchBefore_CheckedChanged(object sender, EventArgs e)
        {
            radioButtonSearchAfter_CheckedChanged(sender, e);
        }

        private void radioButtonSearchBetween_CheckedChanged(object sender, EventArgs e)
        {
            dateTimePickerSearchFrom.Visible = true;
            dateTimePickerSearchTo.Visible = true;
            dateTimePickerSearchFrom.Location = new System.Drawing.Point(184, 22);
            dateTimePickerSearchTo.Location = new System.Drawing.Point(184, 63);
            dateTimePickerSearchTo.MinDate = dateTimePickerSearchFrom.Value;
        }

        private void radioButtonSearchNone_CheckedChanged(object sender, EventArgs e)
        {
            dateTimePickerSearchFrom.Visible = false;
            dateTimePickerSearchTo.Visible = false;
        }

        private void dateTimePickerSearchFrom_ValueChanged(object sender, EventArgs e)
        {
            if (radioButtonSearchBetween.Checked)
            {
                dateTimePickerSearchTo.MinDate = dateTimePickerSearchFrom.Value;
            }
        }

        private Dictionary<string, XmlFile> xmlFilesList;
        public Dictionary<string, XmlFile> XmlFilesList
        {
            get { return xmlFilesList; }
            set { xmlFilesList = value; }
        }

        private DataBase dataBase;
        private SearchingParameters searchingParameters;
        private FileGeneratorUserControl fileGeneratorControl;
        private CompareUserControl compareUserControl;
        private AutomaticTestsUserControl autoTestCtrl;

        private void ClearSearchParameterTextBoxes()
        {
            comboBoxSearchParameterGroup.Text = "";
            comboBoxSearchParameterName.Text = "";
            textBoxSearchParameterValue1.Text = "";
            textBoxSearchParameterValue2.Text = "";
        }

        private void buttonSearchAddParameter_Click(object sender, EventArgs e)
        {
            ParameterSearchValue param = new ParameterSearchValue();
            param.group = comboBoxSearchParameterGroup.Text;
            param.parameterName = comboBoxSearchParameterName.Text;
            param.range = radioButtonSearchParameterRange.Checked;

            string selectedType = (string)labelSearchParameterType.Text;
            if ((string)selectedType == ParameterSearchValue.STRING_TYPE_INT)
            {
                param.valueType = ParameterSearchValue.TYPE_INT;
                try
                {
                    param.value1_int = Convert.ToInt32(textBoxSearchParameterValue1.Text);
                    if (radioButtonSearchParameterRange.Checked)
                    {
                        param.value2_int = Convert.ToInt32(textBoxSearchParameterValue2.Text);
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("One or both values are not integers", "Error", MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    return;
                }
            }
            else if ((string)selectedType == ParameterSearchValue.STRING_TYPE_DOUBLE)
            {
                param.valueType = ParameterSearchValue.TYPE_DOUBLE;
                try
                {
                    param.value1_double = Convert.ToDouble(textBoxSearchParameterValue1.Text);
                    if (radioButtonSearchParameterRange.Checked)
                    {
                        param.value2_double = Convert.ToDouble(textBoxSearchParameterValue2.Text);
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("One or both values are not floating point numbers", "Error", MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    return;
                }
            }
            else if ((string)selectedType == ParameterSearchValue.STRING_TYPE_BOOL)
            {
                param.valueType = ParameterSearchValue.TYPE_BOOL;
                try
                {
                    param.value_bool = Convert.ToBoolean(textBoxSearchParameterValue1.Text);
                }
                catch (Exception)
                {
                    MessageBox.Show("Value is not of boolean type", "Error", MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    return;
                }
            }
            else if ((string)selectedType == ParameterSearchValue.STRING_TYPE_TEXT)
            {
                param.valueType = ParameterSearchValue.TYPE_TEXT;
                param.value_string = textBoxSearchParameterValue1.Text;
            }

            ClearSearchParameterTextBoxes();

            this.parameterViewList.AddParameterView(param);
            searchingParameters.AddParameter(param);
        }

        private void buttonSearchDeleteParameter_Click(object sender, EventArgs e)
        {
            if (parameterViewList.SelectedItem == null)
            {
                return;
            }
            searchingParameters.RemoveParameter(parameterViewList.SelectedItem.Parameter);
            parameterViewList.RemoveSelectedParameterView();
        }

        private void comboBoxSearchParameterName_SelectedIndexChanged(object sender, EventArgs e)
        {
            string fileName;
            if (listBoxXmlFiles.Items.Count == 0)
            {
                return;
            }
            if (listBoxXmlFiles.SelectedItem == null)
            {
                fileName = xmlFilesList.Keys.ToList<string>()[0];
            }
            else
            {
                fileName = (string)(listBoxXmlFiles.SelectedItem);
            }
            XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(xmlFilesList[fileName].content);
            XmlNodeList list = doc.GetElementsByTagName("GROUP");
            foreach (XmlNode node in list)
            {
                if (node.Attributes["NAME"] == null)
                {
                    continue;
                }

                if (node.Attributes["NAME"].Value == comboBoxSearchParameterGroup.Text)
                {
                    XmlNodeList paramList = ((XmlElement)node).GetElementsByTagName("PARAM");
                    foreach (XmlNode param in paramList)
                    {
                        if (param.Attributes["NAME"].Value == comboBoxSearchParameterName.Text)
                        {
                            if( param.Attributes["TYPE"] != null )
                            {
                                labelSearchParameterType.Text = param.Attributes["TYPE"].Value;
                                if (labelSearchParameterType.Text.ToLower() == "float")
                                {
                                    labelSearchParameterType.Text = ParameterSearchValue.STRING_TYPE_DOUBLE;
                                }
                            }
                        }
                    }
                }
            }

            radioButtonSearchParameterValue.Checked = true;
            if (labelSearchParameterType.Text == ParameterSearchValue.STRING_TYPE_INT || labelSearchParameterType.Text == ParameterSearchValue.STRING_TYPE_DOUBLE)
            {
                radioButtonSearchParameterRange.Visible = true;
            }
            else 
            {
                radioButtonSearchParameterRange.Visible = false;
            }
        }

        private void radioButtonSearchParameterValue_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonSearchParameterValue.Checked)
            {
                textBoxSearchParameterValue2.Visible = false;
                textBoxSearchParameterValue1.Size = new System.Drawing.Size(118, 20);
                label1.Visible = false;
                label9.Visible = false;
            }
        }

        private void radioButtonSearchParameterRange_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonSearchParameterRange.Checked)
            {
                textBoxSearchParameterValue2.Visible = true;
                textBoxSearchParameterValue1.Size = new System.Drawing.Size(57, 20);
                label1.Visible = true;
                label9.Visible = true;
            }
        }

        private void buttonAddSearchingTags_Click(object sender, EventArgs e)
        {
            if (comboBoxSearchingTags.SelectedItem == null || listBoxSearchingTags.Items.Contains(comboBoxSearchingTags.SelectedItem))
            {
                return;
            }

            foreach (Tag item in tagPanel1.tagList.Values)
            {
                if (item.name == (string)(comboBoxSearchingTags.SelectedItem))
                {
                    searchingParameters.SearchingTagsIDs.Add(item.id);
                    break;
                }
            }
            listBoxSearchingTags.Items.Add(comboBoxSearchingTags.SelectedItem);
        }

        private void buttonDeleteSearchingTag_Click(object sender, EventArgs e)
        {
            if (listBoxSearchingTags.SelectedItem == null)
            {
                return;
            }

            foreach (Tag item in tagPanel1.tagList.Values)
            {
                if (item.name == (string)(listBoxSearchingTags.SelectedItem))
                {
                    searchingParameters.SearchingTagsIDs.Remove(item.id);
                    break;
                }
            }
            listBoxSearchingTags.Items.Remove(listBoxSearchingTags.SelectedItem);
        }

        private void parameterViewList_Load(object sender, EventArgs e)
        {

        }

        private void comboBoxSearchParameterGroup_Click(object sender, EventArgs e)
        {
            comboBoxSearchParameterGroup.Items.Clear();

            string fileName;
            if( listBoxXmlFiles.Items.Count == 0 )
            {
                return;
            }
            if (listBoxXmlFiles.SelectedItem == null)
            {
                fileName = xmlFilesList.Keys.ToList<string>()[0];
            }
            else
            {
                fileName = (string)( listBoxXmlFiles.SelectedItem );
            }
            XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml( xmlFilesList[fileName].content );
            XmlNodeList list = doc.GetElementsByTagName("GROUP");
            PopulateComboBoxWithXmlTags(ref comboBoxSearchParameterGroup,list);
        }

        private void PopulateComboBoxWithXmlTags( ref ComboBox combo, XmlNodeList list )
        {
            foreach (XmlNode node in list)
            {
                if( node.Attributes["NAME"] == null )
                {
                    continue;
                }

                combo.Items.Add(node.Attributes["NAME"].Value);
            }
        }

        private void comboBoxSearchParameterName_Click(object sender, EventArgs e)
        {
            comboBoxSearchParameterName.Items.Clear();

            string fileName;
            if (listBoxXmlFiles.Items.Count == 0)
            {
                return;
            }
            if (listBoxXmlFiles.SelectedItem == null)
            {
                fileName = xmlFilesList.Keys.ToList<string>()[0];
            }
            else
            {
                fileName = (string)(listBoxXmlFiles.SelectedItem);
            }

            if (string.IsNullOrEmpty(comboBoxSearchParameterGroup.Text))
            {
                return;
            }

            XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(xmlFilesList[fileName].content);
            XmlNodeList list = doc.GetElementsByTagName("GROUP");
            foreach (XmlNode node in list)
            {
                if (node.Attributes["NAME"] == null)
                {
                    continue;
                }

                if (node.Attributes["NAME"].Value == comboBoxSearchParameterGroup.Text)
                {
                    XmlNodeList paramList = ((XmlElement)node).GetElementsByTagName("PARAM");
                    PopulateComboBoxWithXmlTags(ref comboBoxSearchParameterName, paramList);
                }
            }
        }

        private void label5_Click(object sender, EventArgs e)
        {

        }
        
    }
}
